package com.wtgroup.demo.mianshi.线程.d01_wait_notify;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author dafei
 * @version 0.1
 * @date 2021/3/6 18:35
 */
public class D {

    /*
    monitor.wait() / monitor.notify() 前提都需要当前线程必须已经获取当前这个锁(monitor对象).
    否则抛 IllegalMonitorStateException .
    ? 为什么这么设计 ?
    */

    /*
    wait+notify 模拟 生产者-消费者 模式

    输出:

    [1] 条件不满足, wait
    // 等待 5s
    [2] 通知了
    // 等待 5s
    [1] 被唤醒
    [1] 条件满足!
    !!!!!!!!!!!!!!!!!!!

     */

    private final static Object monitor = new Object();

    public static void main(String[] args) throws InterruptedException {
        // monitor.wait();
        // monitor.notify();
        // System.out.println("!!!!!!!!!");

        AtomicBoolean flag = new AtomicBoolean();

        // 线程1 消费者
        Thread t1 = new Thread(() -> {
            synchronized (monitor) {
                while (!flag.get()) {
                    System.out.println("[1] 条件不满足, wait");
                    try {
                        monitor.wait(); // 别人 notify 只是将我从 等待池 移入 等锁池, 等 t2 释放了锁, 我也拿到了锁, 才会继续执行.
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("[1] 被唤醒");
                }
                System.out.println("[1] 条件满足!");
            }
        });

        // 线程2 生产者
        Thread t2 = new Thread(() -> {
            synchronized (monitor) {
                if (!flag.get()) {
                    try {
                        TimeUnit.SECONDS.sleep(5); // 模拟生产过程
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    flag.set(true); // 数据就绪
                    monitor.notify(); // 通知消费者可以使用数据了
                    System.out.println("[2] 通知了");
                    // 测试 消费者 是否立马可执行
                    try {
                        TimeUnit.SECONDS.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();
        System.out.println("!!!!!!!!!!!!!!!!!!!");
    }




}
